/**
 * decode explorer JavaScript
 * @author Erko Risthein <erko@risthein.ee>
 * @copyright Copyright (C) 2009 Erko Risthein
 * @link http://erko.risthein.ee/decode/
 * @license http://www.gnu.org/licenses/ GNU General Public License
 * @package decode_explorer
 */

window.addEvent('domready', function() {
	/* VARIABLES */
	var tbody = $$('tbody')[0];
	var table = $$('table')[0];
	var loading = $('loading');
	var i = 0;
	var iconFolder = './decode/img/';
	var folderIcon = 'folder.png';
	var sortBy = 'name';
	var sortIn = 'asc';
	var currentHash = '#.';
	
	/* EVENTS */
	$$('#breadcrumb a').each(function(a) {
		a.addEvent('click', JSONRequest);
	});
	$('back').addEvent('click', JSONRequest);
	$$('#back a').addEvent('click', JSONRequest);
	$$('.folder').each(function(tr) {
		tr.addEvent('click', JSONRequest);
	});
	$$('.folder a').each(function(a) {
		a.addEvent('click', JSONRequest);
	});
	$$('.file').each(function(tr) {
		tr.addEvent('click', function() { window.location.href = this.getElement('a').getProperty('href') });
	});
	$$('th.name a').addEvent('click', sort);
	$$('th.size a').addEvent('click', sort);
	$$('th.date a').addEvent('click', sort);
	
	
	//checks for a hash and updates the page if needed
	function checkForHash() {
		if (window.location.hash && window.location.hash != currentHash) {
			currentHash = window.location.hash;
			var request = new Request.JSON({
				url: '?path=' + encodeURIComponent(currentHash.replace('#', '')) + '&json=1', //window.location.hash is decoded
				onComplete: updatePage
			}).send();
		} else if (!window.location.hash) { //to make the first back button click working
			window.location.hash = '#.';
		}
	}
	checkForHash(); //call it immediately after pageload
	setInterval(checkForHash, 500); //if the user pressed the back button or changed the hash in some other way, the page gets updated
	
	
	function JSONRequest(e) {
		e.stop();
		var url = this.getProperty('href') ? this.getProperty('href') : this.getElement('a').getProperty('href'); //depends on where the user clicks (on the anchor or on the td tag)
		window.location.hash = url.replace('?path=', '');
		currentHash = window.location.hash;
		var request = new Request.JSON({
			url: url + '&json=1',
			onComplete: updatePage
		}).send();
	};
	
	
	//update the table
	function updatePage(jsonObj) {
		loading.setStyle('display', 'block');
		table.get('tween').start('opacity', 0).chain(function() {
			tbody.empty();
			updateOther(jsonObj.other);
			addFolders(jsonObj.folders);
			addFiles(jsonObj.files);
			table.get('tween').start('opacity', 1);
		}).chain(function() {
			loading.setStyle('display', 'none');
			Slimbox.scanPage();
			isLoading = false;
		});
	}
	
	function updateOther(other) {
		var other = other[0];
		
		var page_title = 'decode explorer: ';
		$('breadcrumb').empty();
		other.breadcrumb.each(function(folder) {
			var a = new Element('a', {'href': '?path=' + folder.path, 'html': folder.name }).inject($('breadcrumb'));
			$('breadcrumb').set('html', $('breadcrumb').get('html') + ' &raquo; ');
			page_title += folder.name + ' » ';
		})
		//trim the last one
		$('breadcrumb').set('html', $('breadcrumb').get('html').replace(/ » $/, ''));
		document.title = page_title.replace(/ » $/, '');
		//addEvent doesn't work in the previous loop for some odd reason
		$$('#breadcrumb a').each(function(a) {
			a.addEvent('click', JSONRequest);
		});
		
		$$('th.name a').setProperty('href', other.name_sort_url).addEvent('click', sort);
		$$('th.size a').setProperty('href', other.size_sort_url).addEvent('click', sort);
		$$('th.date a').setProperty('href', other.date_sort_url).addEvent('click', sort);
		
		$('back').addEvent('click', JSONRequest);
		$('back').getElement('a').setProperty('href', '?path=' + other.parent_folder).addEvent('click', JSONRequest);
		
		$$('.total_objects').setProperty('html', other.total_objects);
		$$('.total_size').setProperty('html', other.total_size);
	};
	
	function addFolders(folders) {
		folders.each(function(folder) {
			var row = new Element('tr', {'class': 'folder ' + alternate('one', 'two')}).addEvent('click', JSONRequest);
			var iconTd = new Element('td').inject(row);
			var icon = new Element('img', {'src': iconFolder + folderIcon, 'alt': '*'}).inject(iconTd);
			var nameTd = new Element('td', {'colspan': 2}).inject(row);
			var name = new Element('a', {'href': '?path=' + folder.url, 'html': folder.name}).inject(nameTd).addEvent('click', JSONRequest);
			var date = new Element('td', {'html': folder.date}).inject(row);
			row.inject(tbody);
		});
	};
	
	function addFiles(files) {
		files.each(function(file) {
			var row = new Element('tr', {'class': 'file ' + alternate('one', 'two')});
			var iconTd = new Element('td').inject(row);
			var icon = new Element('img', {'src': iconFolder + file.icon, 'alt': '*'}).inject(iconTd);
			var nameTd = new Element('td').inject(row);
			var nameUrl = new Element('a', {'href': file.url, 'html': file.name}).inject(nameTd);
			var size = new Element('td', {'html': file.size, 'title': file.size_in_bytes + ' bytes'}).inject(row);
			var date = new Element('td', {'html': file.date}).inject(row);
			row.inject(tbody);
		});
	};
	
	/* alternates between two values */
	function alternate(value1, value2) {
		return (i++ % 2 == 0 ? value1 : value2);
	}
	
	/* sorting */
	function sort(e) {
		var folders = tbody.getElements('.folder');
		var files = tbody.getElements('.file');
		if (this.getParent().getProperty('class') == 'name') {
			folders.sort(nameCmp);
			files.sort(nameCmp)
			sortBy = 'name';
		}
		if (this.getParent().getProperty('class') == 'size') {
			folders.sort(nameCmp); //no size for folders
			files.sort(sizeCmp)
			sortBy = 'size';
		}
		if (this.getParent().getProperty('class') == 'date') {
			folders.sort(dateCmp);
			files.sort(dateCmp)
			sortBy = 'date';
		}
		
		if (sortIn == 'asc') {
			folders.reverse();
			files.reverse();
		}
		
		//add classes in proper order, so the table zebra-striping wouldn't mess up
		folders.each(function(row) { row.setProperty('class', alternate('folder one', 'folder two')).inject(tbody); });
		files.each(function(row) { row.setProperty('class', alternate('file one', 'file two')).inject(tbody); });
		
		sortIn = sortIn == 'asc' ? 'desc' : 'asc';
		
		//sorting arrows
		$$('th.name img').setProperty('src', iconFolder + 'arrow_' + (sortBy == 'name' ? sortIn : 'blank') + '.png');
		$$('th.size img').setProperty('src', iconFolder + 'arrow_' + (sortBy == 'size' ? sortIn : 'blank') + '.png');
		$$('th.date img').setProperty('src', iconFolder + 'arrow_' + (sortBy == 'date' ? sortIn : 'blank') + '.png');
		
		return false;
	}
	
	/* comparators */
	function nameCmp(r1, r2) {
		//toUpperCase so it would sort case insensitively
		var v1 = String(r1.getElements('td')[1].getElements('a').getProperty('html')).toUpperCase();
		var v2 = String(r2.getElements('td')[1].getElements('a').getProperty('html')).toUpperCase();
		
		return cmp(v1, v2);
	}
	
	function sizeCmp(r1, r2) {
		//titles hold the sizes in bytes
		var v1 = parseInt(r1.getElements('td')[2].getProperty('title'));
		var v2 = parseInt(r2.getElements('td')[2].getProperty('title'));
		
		return cmp(v1, v2);
	}
	
	function dateCmp(r1, r2) {
		var a1 = r1.getElements('td');
		var a2 = r2.getElements('td');
		var v1 = a1[a1.length - 1].getProperty('html');
		var v2 = a2[a2.length - 1].getProperty('html');
		
		return cmp(v1, v2);
	}
	
	function cmp(v1, v2) {
		if (v1 > v2) {
			return 1;
		} else if (v1 < v2) {
			return -1;
		}
		return 0;
	}

});